// utils/mac_recv.go
package Utils

import (
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/pcap"
	"log"
	"net"
	"os"
	"reflect"
	"sync/atomic"
	"syscall"
	"time"
	"unsafe"
)

// ====================== 回调接口 ======================
type MacDataCallback interface {
	RecvMacData(data []byte)
}

// ====================== 默认配置常量 ======================
const (
	defaultSnapshotLen  = int32(65536)
	defaultPromiscuous  = true
	defaultTimeout      = 1 * time.Second
	defaultKernelBuffer = 100 * 1024 * 1024 // 100MB
)

// ====================== 主结构体 ======================
type MacRecv struct {
	deviceName string
	localMAC   net.HardwareAddr
	remoteMAC  net.HardwareAddr
	callback   MacDataCallback
	handle     *pcap.Handle

	snapshotLen  int32
	promiscuous  bool
	timeout      time.Duration
	kernelBuffer int

	startTime time.Time
	stopFlag  atomic.Bool

	// 新增统计字段（之前漏了！）
	totalPackets   uint64
	matchedPackets uint64

	packetSource *gopacket.PacketSource
}

// ====================== 构造函数 ======================
func NewMacRecv(device, localMacStr, remoteMacStr string, cb MacDataCallback) (*MacRecv, error) {
	localMAC, err := net.ParseMAC(localMacStr)
	if err != nil {
		return nil, fmt.Errorf("local MApacketLoopC 解析失败: %v", err)
	}
	remoteMAC, err := net.ParseMAC(remoteMacStr)
	if err != nil {
		return nil, fmt.Errorf("remote MAC 解析失败: %v", err)
	}

	return &MacRecv{
		deviceName: device,
		localMAC:   localMAC,
		remoteMAC:  remoteMAC,
		callback:   cb,

		snapshotLen:  defaultSnapshotLen,
		promiscuous:  defaultPromiscuous,
		timeout:      defaultTimeout,
		kernelBuffer: defaultKernelBuffer,

		startTime: time.Now(),
	}, nil
}
func (m *MacRecv) Start() error {

	// ----------- 测试模式：不打开真实网卡 -----------
	if m.packetSource != nil {
		go m.packetLoop()
		return nil
	}

	// ----------- 正常模式：打开真实网卡 -----------
	var err error
	m.handle, err = pcap.OpenLive(m.deviceName, m.snapshotLen, m.promiscuous, m.timeout)
	if err != nil {
		return fmt.Errorf("打开网卡失败 %s: %w", m.deviceName, err)
	}

	// 设置内核 buffer
	v := reflect.ValueOf(m.handle)
	if v.Kind() == reflect.Ptr && !v.IsNil() {
		elem := v.Elem()
		method := elem.MethodByName("GetSyscallHandle")
		if method.IsValid() {
			ret := method.Call(nil)
			if len(ret) == 1 {
				sysHandle := ret[0].Uint()

				const BIOCSBLEN = 0x4004696a
				size := uint32(m.kernelBuffer)

				r0, _, errNo := syscall.SyscallN(
					0x80000000|BIOCSBLEN,
					uintptr(sysHandle),
					BIOCSBLEN,
					uintptr(unsafe.Pointer(&size)),
				)

				if r0 == 0 {
					log.Printf("Kernel buffer 设置成功：%d MB", m.kernelBuffer/(1024*1024))
				} else {
					log.Printf("Kernel buffer 设置失败: r0=%d, err=%v", r0, errNo)
				}
			}
		}
	}

	// BPF 过滤
	if err := m.handle.SetBPFFilter("ether[12:2] = 0x509a"); err != nil {
		log.Printf("警告：BPF 设置失败: %v", err)
	}

	log.Printf("开始抓包 → %s | kernel buffer = %d MB", m.deviceName, m.kernelBuffer/(1024*1024))

	go m.packetLoop()
	return nil
}

//func (m *MacRecv) Start() error {
//	var err error
//	m.handle, err = pcap.OpenLive(m.deviceName, m.snapshotLen, m.promiscuous, m.timeout)
//	if err != nil {
//		return fmt.Errorf("打开网卡失败 %s: %w", m.deviceName, err)
//	}
//
//	v := reflect.ValueOf(m.handle)
//	if v.Kind() == reflect.Ptr && !v.IsNil() {
//		elem := v.Elem()
//		method := elem.MethodByName("GetSyscallHandle")
//		if method.IsValid() {
//			ret := method.Call(nil)
//			if len(ret) == 1 {
//				sysHandle := ret[0].Uint()
//
//				const BIOCSBLEN = 0x4004696a
//				size := uint32(m.kernelBuffer)
//
//				r0, _, errNo := syscall.SyscallN(
//					0x80000000|BIOCSBLEN, // 直接用 ioctl 码作为 trap
//					uintptr(sysHandle),
//					BIOCSBLEN,
//					uintptr(unsafe.Pointer(&size)),
//				)
//
//				if r0 == 0 {
//					log.Printf("Kernel buffer 设置成功：%d MB", m.kernelBuffer/(1024*1024))
//				} else {
//					log.Printf("Kernel buffer 设置失败（可继续抓包）: r0=%d, err=%v", r0, errNo)
//				}
//			}
//		}
//	}
//
//	// BPF 过滤：EtherType = 0x509a → ether[12:2] = 0x509a
//	if err := m.handle.SetBPFFilter("ether[12:2] = 0x509a"); err != nil {
//		log.Printf("警告：BPF 过滤设置失败（继续无过滤）: %v", err)
//	}
//
//	log.Printf("开始抓包 → %s | kernel buffer = %d MB", m.deviceName, m.kernelBuffer/(1024*1024))
//
//	go m.packetLoop()
//	return nil
//}

// ====================== Stop ======================
func (m *MacRecv) Stop() {
	m.stopFlag.Store(true)
	if m.handle != nil {
		m.handle.Close()
	}

	duration := time.Since(m.startTime).Seconds()
	if duration < 1 {
		duration = 1
	}
	matched := atomic.LoadUint64(&m.matchedPackets)
	totalBytes := matched * 8224
	speedMbps := float64(totalBytes*8) / duration / 1e6

	log.Printf("=== 抓包停止 ===")
	log.Printf("总包数: %d | 匹配包数: %d", atomic.LoadUint64(&m.totalPackets), matched)
	log.Printf("运行时间: %.1f 秒 | 平均速率: %.2f Mbps (%.3f Gbps)",
		duration, speedMbps, speedMbps/1000)
}

// ====================== 抓包主循环 ======================
func (m *MacRecv) packetLoop() {
	//src := gopacket.NewPacketSource(m.handle, m.handle.LinkType())
	var src *gopacket.PacketSource
	if m.packetSource != nil {
		// 测试模式：使用注入的 source
		src = m.packetSource
	} else {
		// 正常模式
		src = gopacket.NewPacketSource(m.handle, m.handle.LinkType())
	}
	src.NoCopy = true // 零拷贝！

	for packet := range src.Packets() {
		if m.stopFlag.Load() {
			break
		}

		atomic.AddUint64(&m.totalPackets, 1)

		data := packet.Data()
		if len(data) != 8224 { // 严格匹配你原来的包长
			continue
		}

		// 快速判断 EtherType（虽然 BPF 已过滤，但保险）
		if data[12] != 0x50 || data[13] != 0x9a {
			continue
		}

		atomic.AddUint64(&m.matchedPackets, 1)

		// 跳过：以太网头14字节 + 你自定义的 32 + 104 字节协议头
		payload := data[14+32+104:]
		if len(payload) < 6*1296 {
			continue
		}

		m.parseAndCallback(payload)
	}
}

// ====================== 解析并回调 ======================
func (m *MacRecv) parseAndCallback(data []byte) {
	const subLen = 1296
	if m.callback == nil {
		return
	}

	for i := 0; i < 6; i++ {
		start := i * subLen
		if start+subLen > len(data) {
			break
		}
		sub := data[start : start+subLen]

		// 可选：恢复你原来的魔数校验
		// if sub[0] != 0x13 || sub[1] != 0x20 || sub[2] != 0x10 || sub[3] != 0x05 {
		// 	continue
		// }

		// 必须深拷贝！否则上层持有引用可能导致野指针
		cpy := make([]byte, subLen)
		copy(cpy, sub)
		m.callback.RecvMacData(cpy)
	}
}

// ====================== 示例回调 ======================
type fileWriterCallback struct {
	f *os.File
}

func (c *fileWriterCallback) RecvMacData(data []byte) {
	if c.f != nil {
		c.f.Write(data) // 直接落盘
	}
	// 可选打印调试信息
	// if len(data) >= 12 {
	// 	ch := uint16(data[6]) | uint16(data[7])<<8
	// 	frame := uint32(data[8]) | uint32(data[9])<<8 | uint32(data[10])<<16 | uint32(data[11])<<24
	// 	fmt.Printf("ch=%d frame=%d\n", ch, frame)
	// }
}
